﻿#include "EasyIOCPClient.h"

#ifdef _WIN32

EasyIOCPClient::~EasyIOCPClient()
{
	EasyTcpClient::Close();
}

void EasyIOCPClient::Close()
{
	_iocp.destory();
	EasyTcpClient::Close();
}

void EasyIOCPClient::OnInitSocket()
{
	_iocp.create();
	_iocp.reg(_pClient->sockfd(), _pClient);
}

void EasyIOCPClient::OnConnect()
{

}

// 发送数据
// 处理网络消息
bool EasyIOCPClient::OnRun(int microseconds)
{
	if (IsRun())
	{
		if (_pClient->needWrite())
		{
			auto pIoData = _pClient->makeSendIOData();
			if (pIoData)
			{
				if (!_iocp.postSend(pIoData))
				{
					Close();
					return false;
				}
			}
			//--
			pIoData = _pClient->makeRecvIOData();
			if (pIoData)
			{
				if (!_iocp.postRecv(pIoData))
				{
					Close();
					return false;
				}
			}
		}
		else {
			auto pIoData = _pClient->makeRecvIOData();
			if (pIoData)
			{
				if (!_iocp.postRecv(pIoData))
				{
					Close();
					return false;
				}
			}
		}

		// 循环处理事件直到没有事件发生为止
		while (true)
		{
			int ret = DoNetIOCPEvents(microseconds);
			if (ret < 0)
			{
				// IOCP出错
				return false;
			}
			else if (ret == 0)
			{
				// 没有事件发生
				// 处理数据
				DoMsg();
				return true;
			}
		}
		DoMsg();
		return true;
	}
	return false;
}

int EasyIOCPClient::DoNetIOCPEvents(int timeout)
{
	int ret = _iocp.wait(_ioEvent, timeout);
	if (ret < 0)
	{
		// IOCP出错
		CELLLog_Error("EasyIOCPClient::DoNetEvents wait clientID<%d> socket<%d>", _pClient->id, (int)_pClient->sockfd());
		return ret;
	}
	else if (ret == 0)
	{
		// 没有事件发生
		return ret;
	}

	// 接收数据
	if (IO_TYPE::RECV == _ioEvent.pIOData->iotype)
	{// 接收数据完成
		if (_ioEvent.bytesTrans <= 0)
		{// 客户端断开
			CELLLog_Error("EasyIOCPClient::DoNetIOCPEvents rmclient sockfd=%d", (int)_ioEvent.pIOData->sockfd);
			Close();
			return ret;
		}
		// 告诉接收数据的客户端本次接收到了多少数据，用于接收缓冲区的数据位置的偏移
		CELLClient* pClient = (CELLClient*)_ioEvent.data.ptr;
		if (pClient)
			pClient->recv4Iocp(_ioEvent.bytesTrans);
		// CELLLog_Info("recv data: sockfd=%d, bytesTrans=%d", (int)_ioEvent.pIOData->sockfd, _ioEvent.bytesTrans);
	}
	else if (IO_TYPE::SEND == _ioEvent.pIOData->iotype)
	{// 发送数据完成
		if (_ioEvent.bytesTrans <= 0)
		{// 客户端断开
			CELLLog_Error("EasyIOCPClient::DoNetIOCPEvents rmclient sockfd=%d", (int)_ioEvent.pIOData->sockfd);
			Close();
			return ret;
		}
		// 通知发送缓冲区发送了多少数据
		CELLClient* pClient = (CELLClient*)_ioEvent.data.ptr;
		if (pClient)
			pClient->send2Iocp(_ioEvent.bytesTrans);
		// CELLLog_Info("send data: sockfd=%d, bytesTrans=%d", (int)_ioEvent.pIOData->sockfd, _ioEvent.bytesTrans);
	}
	else
	{
		//
		CELLLog_Error("undefined iotype");
	}
	return ret;
}

#endif // #ifdef _WIN32
